﻿#include<iostream>
using namespace std;

auto ave(int a, int b) {
	return a + b;
}

auto bigger(int& a, int& b)->int& {//拖尾函数，强制返回int引用，当然，不一定非要返回引用
	return a > b ? a : b;
}
auto bigger(int& a, int& b)->decltype(a > b ? a : b) {//C++11以后利用decltype特性可以以下写法，但是比较累赘
	return a > b ? a : b;
}
decltype(auto) bigger(int& a, int& b) {//C++14以后写法
	return a > b ? a : b;
}

int main() {
	char a;
	auto b{ &a };//变成指针

	const int c{ 1 };
	auto b = c;//变成int类型，并不是const类型

	int e{ 234 };
	int& e1{ e };
	auto b = e1;//变成int类型，而非int&

	auto b = ave(1, 2);//利用函数返回值来确定类型

	int f{ 324 }, g{ 123 };
	bigger(f, g) = 500;
	cout << f << endl;//500
	cout << g << endl;//123

	decltype(a + b--) x;//只是根据表达式得到类型，能保留const、引用和指针，但是没有初始化

	//如果decltype内的表达式经历了运算，那么得出的数据类型是根据运算结果是否有固定的内存地址（左值）来决定的，如果有固定的内存地址则得出的类型为该类型的引用类型，如果没有固定的内存地址，则得出的类型为该结果的类型
	int h{ 100 }, i{ 200 };
	int* ha{ &h };
	decltype(a + b) x;//相当于int x
	decltype(*ha) x;//相当于int& x
	decltype(ha[0])x;//相当于int& x
	decltype((h)) x;//加个括号也算作一次运算，所以相当于int& x

	//如果decltype内的表达式是一个函数，那么得出的数据类型是根据函数的返回类型来确定的
	decltype(ave(100, 200)) x;//相当于int x
	//decltype不会真的执行表达式的运算，因此ave函数并未执行
	//auto则会执行函数，根据返回类型确定类型


}